<?php
/**
 * Eren PHP Server Framework
 * 
 * The Semaphore class, you will need this when you using mutiple process or mutiple thread.
 * 
 * @category System
 * @author Steve Liu
 * @copyright Eshifang (http://www.eshifang.com)
 */

class System_Semaphore
{ 
    /**
     * Get or Create an Seamphore, first call to this method 
     * using key will Create,a second call to this method using 
     * the same key will be Get.
     * 
     * @param int $key
     * @param int $maxAcquire
     * @param int $perm
     * @param bool $autoRelease
     * @throws System_Exception
     * 
     * @return resource
     */
    public static function get($key, $maxAcquire = 1, $perm = 0666, $autoRelease = TRUE)
    {
        if(!is_int($key)|| $key<=0 || $key>=0xfff){
            throw new System_Exception('The param $key must be int between 1 and 65534');
        }
        
        if(!is_int($maxAcquire)){
            throw new System_Exception('The param $maxAcquire must be int');
        }
        
        if(!is_int($perm)){
            throw new System_Exception('The param $perm must be int');
        }
        
        if(!is_bool($autoRelease)){
            throw new System_Exception('The param $autoRelease must be bool');
        }
        
        $key += System_Config::IPCKeyPre();
        
        if(($ret = sem_get($key, $maxAcquire, $perm, $autoRelease)) === FALSE){
            throw new System_Exception('Can\'t create or get semaphore');
        }
        
        return $ret;
    }
    
    /**
     * Acquire an semaphore
     * 
     * @param resource $id
     * @throws System_Exception
     * 
     * @return bool
     */
    public static function acquire($id)
    {
        if(!is_resource($id)){
            throw new System_Exception('The param $id must be resource which get from System_Semaphore::get()');
        }
        
        if(($ret = sem_acquire($id) === FALSE)){
            throw new System_Exception('Can\'t acquire semaphore');
        }
        
        return $ret;
    }
    
    /**
     * Release an semaphore
     * 
     * @param resource $id
     * @throws System_Exception
     * 
     * @return bool
     */
    public static function release($id)
    {
        if(!is_resource($id)){
            throw new System_Exception('The param $id must be resource which get from System_Semaphore::get()');
        }
        
        if(($ret = sem_release($id) === FALSE)){
            throw new System_Exception('Can\'t release semaphore');
        }
        
        return $ret;
    }
    
    /**
     * Remove the semaphore
     * 
     * @param resource $id
     * @throws System_Exception
     * 
     * @return bool
     */
    public static function remove($id)
    {
        if(!is_resource($id)){
            throw new System_Exception('The param $id must be resource which get from System_Semaphore::get()');
        }
        
        if(($ret = sem_remove($id) === FALSE)){
            throw new System_Exception('Can\'t remove semaphore');
        }
        
        return $ret;
    }
}